/**
 * プルダウンリストコンポーネント
 *  usage:
 *   import { SelectItemList, SelectItem } from './SelectItemList';
 *   <SelectItemList name={項目名} value={選択値} placeholder="選択してください">
 *     {CONSTANT.choices.map((choice, idx) => <SelectItem key={idx} value={choice.value} label={choice.label}/>)}
 *   </SelectItemList>
 */
import React, { Component, PureComponent } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import './SelectItemList.css';

// 未入力（プレースホルダの内部コード値）
const DEFUALT_PLACEHOLDER_VALUE = -1;

export class SelectItem extends PureComponent {
  render() {
    const { value, label, className } = this.props;
    return (
      <option className={classNames('SelectItem', className)} key={value} value={value}>{label}</option>
    );
  }
}

SelectItem.propTypes = {
  value: PropTypes.number,              // 選択値
  label: PropTypes.string.isRequired,   // 選択ラベル
  className: PropTypes.string,          // class属性
};

export class SelectItemList extends Component {
  constructor(props) {
    super(props);
    this.state = { value: this._correct(props.value) };
  }

  componentWillReceiveProps(nextProps) {
    this.setState({ value: this._correct(nextProps.value) });
  }

  // 未入力の場合、プレースホルダ値に補正
  _correct(value) {
    const { placeholderValue = DEFUALT_PLACEHOLDER_VALUE } = this.props;
    return (value === null || value === undefined || isNaN(value) || value === placeholderValue) ? placeholderValue : value;
  }
  // プレースホルダが選択されているかどうか
  _isPlaceholder(value) {
    const { placeholderValue = DEFUALT_PLACEHOLDER_VALUE } = this.props;
    return value === placeholderValue;
  }
  // プレースホルダ値の場合、未入力に戻す
  _restore(value) {
    return this._isPlaceholder(value) ? this.props.placeholderValue : value;
  }

  handleChange(event) {
    const { name } = this.props;
    let value = this.input.value;
    value = value ? Number(value) : null;
    this.setState({ value }, () => {
      value = this._restore(value);   // プレースホルダ値の場合は、未入力に戻す
      if (this.props.propagate(name, value, true) !== false) {
        this.props.onChange(name, value);
      }
    });
  }

  render() {
    // eslint-disable-next-line no-unused-vars
    const { name, value, className, disabled, placeholder, placeholderValue = DEFUALT_PLACEHOLDER_VALUE, onChange, propagate, children, ...other } = this.props;
    return (
      <div className="SelectItemListContainer">
        <select
          {...other}
          id={name}
          name={name}
          className={classNames('SelectItemList', className, {
            'disabled': disabled,
            'placeholder': this._isPlaceholder(this.state.value),
          })}
          value={this.state.value}
          disabled={disabled}
          onChange={this.handleChange.bind(this)}
          ref={input => this.input = input}
        >
          {(!placeholder) ? children : [
            <SelectItem key="placeholder" value={placeholderValue} label={placeholder} className="placeholder"/>,
            ...children,
          ]}
        </select>
      </div>
    );
  }
}

SelectItemList.propTypes = {
  name: PropTypes.oneOfType([PropTypes.string, PropTypes.shape({
    id: PropTypes.string.isRequired,
    label: PropTypes.string.isRequired,
    choices: PropTypes.array.isRequired,
  })]).isRequired,                      // id
  value: PropTypes.number,              // 入力値（初期値）
  className: PropTypes.string,          // class属性
  style: PropTypes.object,              // style属性
  disabled: PropTypes.bool,             // disabled属性
  placeholder: PropTypes.string,        // プレースホルダーテキスト
  placeholderValue: PropTypes.number,   // プレースホルダー選択値
  onChange: PropTypes.func,             // change event handler
  propagate: PropTypes.func.isRequired, // 親stateを更新するcallback
  children: PropTypes.arrayOf(PropTypes.element).isRequired,
};

SelectItemList.defaultProps = {
  disabled: false,
  onChange: () => {},
  propagate: () => {},
};
